package com.cjd.common.utils

import android.annotation.SuppressLint
import android.text.TextUtils
import android.util.Log
import java.sql.Timestamp
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

/**
 * @Author chenjidong
 * @email 374122600@qq.com
 * created 2017/6/19.
 * description
 */
object DateUtils {

    val FORMAT_DATETIME = "yyyy-MM-dd HH:mm:ss"
    val FORMAT_DATETIME_yMdHm = "yyyy-MM-dd HH:mm"
    val FORMAT_DATE = "yyyy-MM-dd"
    val FORMAT_MONTH = "yyyy-MM"
    val FORMAT_HOUR = "HH:mm"

    private val SECOND_MILLIS = 1000L
    private val MINUTE_MILLIS = 60 * SECOND_MILLIS
    private val HOUR_MILLIS = 60 * MINUTE_MILLIS
    private val DAY_MILLIS = 24 * HOUR_MILLIS
    var WEEK_MILLIS = 7 * DAY_MILLIS


    private val ONE_HOUR_MILLIS = (60 * 60 * 1000).toLong() // 一小时的毫秒数
    private val ONE_DAY_MILLIS = 24 * ONE_HOUR_MILLIS // 一天的毫秒数

    fun getYyyyMmDd(date: Date): String {
        val format = SimpleDateFormat(FORMAT_DATE)
        return format.format(date)
    }

    fun getHHmm(date: String): String {
        val format = SimpleDateFormat(FORMAT_HOUR)
        val date1 = getDateFull(date)
        return if (date1 == null) "" else format.format(date1)
    }

    fun getDateFull(date: Date): String {
        val format = SimpleDateFormat(FORMAT_DATETIME)
        return format.format(date)
    }

    fun getDateFull(date: String): Date? {
        val format = SimpleDateFormat(FORMAT_DATETIME)
        try {
            return format.parse(date)
        } catch (e: Exception) {
            return null
        }

    }

    fun getMmDd(date: Date): String {
        val format = SimpleDateFormat("MM-dd")
        return format.format(date)
    }

    fun getChineseMmDd(date: Date): String {
        val format = SimpleDateFormat("MM月dd日")
        return format.format(date)
    }

    fun getDate(date: String): Date? {
        val format = SimpleDateFormat(FORMAT_DATE)
        try {
            return format.parse(date)
        } catch (e: ParseException) {
            return null
        }

    }

    fun getDateInString(stringDate: String): String {
        val today = getYyyyMmDd(Date())
        val one = getDate(stringDate)
        val two = getDate(today)
        val i = (Math.abs(one!!.time - two!!.time) / ONE_DAY_MILLIS).toInt()
        return if (i == 0) {
            "今天"
        } else if (i == 1) {
            "明天"
        } else if (i == 2) {
            "后天"
        } else {
            dayForWeek(stringDate)
        }
    }

    fun getBetweenDayNumber(dateA: Date, dateB: Date): Int {
        val dayNumber: Long
        dayNumber = (dateB.time - dateA.time) / ONE_DAY_MILLIS
        return if (dayNumber.toInt() > 0) dayNumber.toInt() else 1
    }

    /**
     * 判断当前日期是星期几
     *
     * @param pTime 修要判断的时间
     * @return dayForWeek 判断结果
     * @Exception 发生异常
     */
    fun dayForWeek(pTime: String): String {
        val c = Calendar.getInstance()
        c.time = getDate(pTime)!!
        var dayStr = ""
        when (c.get(Calendar.DAY_OF_WEEK)) {
            Calendar.MONDAY -> dayStr = "周一"
            Calendar.TUESDAY -> dayStr = "周二"
            Calendar.WEDNESDAY -> dayStr = "周三"
            Calendar.THURSDAY -> dayStr = "周四"
            Calendar.FRIDAY -> dayStr = "周五"
            Calendar.SATURDAY -> dayStr = "周六"
            Calendar.SUNDAY -> dayStr = "周日"
            else -> dayStr = ""
        }

        return dayStr
    }

    /**
     * 判断是否是 周末
     *
     * @param dateA 开始时间必须小于 dateB 否则返回false
     * @param dateB
     * @return
     */
    fun getWorkday(dateA: Date, dateB: Date): Boolean {
        val c1 = Calendar.getInstance()
        val c2 = Calendar.getInstance()
        c1.time = dateA
        c2.time = dateB

        return if (dateA.time < dateB.time && (c1.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY && (c2.get(
                Calendar.DAY_OF_WEEK
            ) == Calendar.SATURDAY || c2.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) || c1.get(
                Calendar.DAY_OF_WEEK
            ) == Calendar.SATURDAY && c2.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
        ) true else false
    }


    fun interval(beginDate: Date, endDate: Date): DateInterval? {
        try {
            val df = SimpleDateFormat(FORMAT_DATETIME)
            val now = df.parse(getDateFull(endDate))
            val date = df.parse(getDateFull(beginDate))
            val detail = DateInterval()
            val l = now.time - date.time
            val day = l / (24 * 60 * 60 * 1000)
            val hour = l / (60 * 60 * 1000) - day * 24
            val min = l / (60 * 1000) - day * 24 * 60 - hour * 60
            val s = l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60
            detail.day = day
            detail.hour = hour
            detail.minute = min
            detail.second = s
            return detail
        } catch (e: ParseException) {
            e.printStackTrace()
        }

        return null
    }

    class DateInterval {
        var day: Long = 0
        var hour: Long = 0
        var minute: Long = 0
        var second: Long = 0
    }

    /**
     * 用户自己定义日期和格式，进行格式化
     *
     * @param date    用户指定的日期
     * @param pattern 用户指定的时间格式
     * @return 返回指定的格式化后的时间字符串
     */
    fun formatDate(date: Date?, pattern: String): String? {
        if (date == null || TextUtils.isEmpty(pattern)) {
            return null
        }
        val datePattern = SimpleDateFormat(pattern)

        return datePattern.format(date)
    }

    /**
     * 对指定的日期，使用 yyyy-MM 形式进行格式化
     *
     * @param date 指定的日期
     * @return 返回 yyyy-MM 格式的字符串
     */
    fun getMonthStr(date: Date?): String? {
        return if (date == null) {
            null
        } else SimpleDateFormat(FORMAT_MONTH).format(date)
    }

    /**
     * 对指定的日期，使用 yyyy-MM-dd 形式进行格式化
     *
     * @param date 指定的日期
     * @return 返回 yyyy-MM-dd 格式的字符串
     */
    fun getDateStr(date: Date?): String? {
        return if (date == null) {
            null
        } else SimpleDateFormat(FORMAT_DATE).format(date)
    }

    /**
     * 对指定的毫秒数，使用 yyyy-MM-dd 形式进行格式化
     *
     * @param timeMillis 指定的毫秒数
     * @return 返回 yyyy-MM-dd 格式的字符串
     */
    fun getDateStr(timeMillis: Long): String? {
        return getDateStr(Date(timeMillis))
    }

    /**
     * 对指定的日期，使用 yyyy-MM-dd HH:mm:ss 形式进行格式化
     *
     * @param date 指定的日期
     * @return 返回 yyyy-MM-dd HH:mm:ss 格式的字符串
     */
    fun getDateTimeStr(date: Date?): String? {
        return if (date == null) {
            null
        } else SimpleDateFormat(FORMAT_DATETIME).format(date)
    }

    /**
     * 对指定的日期，使用 yyyy-MM-dd HH:mm 形式进行格式化
     *
     * @param date 指定的日期
     * @return 返回 yyyy-MM-dd HH:mm 格式的字符串
     */
    fun getDateTimeyMdHmStr(date: Date?): String? {
        return if (date == null) {
            null
        } else SimpleDateFormat(FORMAT_DATETIME_yMdHm).format(date)
    }

    /**
     * 对指定的毫秒数，使用 yyyy-MM-dd HH:mm:ss 形式进行格式化
     *
     * @param timeMillis 指定的毫秒数
     * @return 返回 yyyy-MM-dd HH:mm:ss 格式的字符串
     */
    fun getDateTimeStr(timeMillis: Long): String? {
        return getDateTimeStr(Date(timeMillis))
    }

    /**
     * @return 返回当前时间的 yyyy-MM-dd 格式的字符串
     */
    fun getCurrentDateStr(): String? {
        return getDateStr(Date())
    }

    /**
     * @return 返回当前时间的 yyyy-MM-dd 格式的字符串
     */
    fun getCurrentDate(): Date? {
        return convert(getCurrentTimestamp())
    }

    /**
     * @return 返回当前时间的 yyyy-MM-dd HH:mm:ss 格式的字符串
     */
    fun getCurrentDateTimeStr(): String? {
        return getDateTimeStr(Date())
    }

    /**
     * @return 返回当前时间的 yyyy-MM 格式的字符串
     */
    fun getCurrentMonthStr(): String? {
        return getMonthStr(Date())
    }

    /**
     * 在指定的日期的基础上添加指定单位的数值，然后格式化成 yyyy-MM-dd HH:mm:ss 的字符串后返回
     *
     * @param date     指定的日期
     * @param diffTime 指定的时间数值（如果需要减，则使用负数即可）
     * @param unit     指定的时间单位
     * @return 返回 yyyy-MM-dd HH:mm:ss 格式的字符串
     */
    fun timeAddToStr(date: Date?, diffTime: Long, unit: TimeUnit): String? {
        if (date == null) {
            return null
        }
        val resultTime = date.time + unit.toMillis(diffTime)

        return getDateTimeStr(resultTime)
    }


    /**
     * 在指定的日期的基础上添加指定单位的数值，并返回
     *
     * @param date     指定的日期
     * @param diffTime 指定的时间数值，可以为负数
     * @param unit     指定的时间单位
     * @return 返回计算之后的日期
     */
    fun timeAdd(date: Date?, diffTime: Long, unit: TimeUnit): Date? {
        if (date == null) {
            return null
        }
        val resultTime = date.time + unit.toMillis(diffTime)

        return Date(resultTime)
    }

    /**
     * 在指定的日期上添加指定days天数，然后返回
     *
     * @param date 指定的日期
     * @param days 需要添加的天数，可以为负数
     * @return 在指定的日期上添加指定days天数，然后返回
     */
    @SuppressLint("NewApi")
    fun timeAddByDays(date: Date, days: Int): Date? {
        return timeAdd(date, days.toLong(), TimeUnit.DAYS)
    }

    /**
     * @param date   日期
     * @param months 需要添加的月份数，可以为负数
     * @return 在指定的日期上添加指定months个月，然后返回
     */
    fun timeAddByMonth(date: Date?, months: Int): Date? {
        if (date == null) {
            return null
        }
        if (months == 0) {
            return date
        }

        val cal = Calendar.getInstance()
        cal.time = date
        cal.add(Calendar.MONTH, months)

        return cal.time
    }

    /**
     * 返回指定日期所在月份的第一天的日期
     *
     * @param date
     * @return 返回指定日期所在月份的第一天的日期
     */
    fun getFirstDayOfMonth(date: Date?): String? {
        if (date == null) {
            return null
        }
        val cal = Calendar.getInstance()
        cal.time = date
        cal.set(Calendar.DAY_OF_MONTH, 1)

        return getDateStr(cal.time)
    }

    /**
     * @return 返回昨天的日期字符串，格式为 yyyy-MM-dd
     */
    @SuppressLint("NewApi")
    fun getYestoday(): String {
        return timeAddToStr(
            Date(),
            -1,
            TimeUnit.DAYS
        )!!.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]
    }


    /**
     * 按照 yyyy-MM-dd 的格式解析给定的日期字符串
     *
     * @param dateStr 给定的日期字符串
     * @return 返回解析后的日期，如果解析失败，则返回null
     */
    fun parseDate(dateStr: String): Date? {
        try {
            return SimpleDateFormat(FORMAT_DATE).parse(dateStr)
        } catch (e: ParseException) {
            Log.e("dateUtil", "parseDate exception : ", e)
        }

        return null
    }

    /**
     * 按照 yyyy-MM-dd HH:mm:ss 的格式解析给定的日期字符串
     *
     * @param dateTimeStr 给定的日期字符串
     * @return 返回解析后的日期，如果解析失败，则返回null
     */
    fun parseDateTime(dateTimeStr: String): Date? {
        try {
            return SimpleDateFormat(FORMAT_DATETIME).parse(dateTimeStr)
        } catch (e: ParseException) {
            Log.e("dateUtil", "parseDateTime exception : ", e)
        }

        return null
    }

    /**
     * 按照指定的format格式解析给定的日期字符串
     *
     * @param dateStr 给定的日期字符串
     * @param format  指定的日期格式
     * @return 将日期字符串解析成Date对象
     */
    fun parseToDate(dateStr: String, format: String): Date? {
        val sdf = SimpleDateFormat(format)
        var date: Date? = null
        try {
            date = sdf.parse(dateStr)
        } catch (e: ParseException) {
            Log.e("dateUtil", "parseToDate exception : ", e)
        }

        return date
    }

    /**
     * 将给定的日期字符串按照 yyyy-MM-dd HH:mm:ss 格式解析成Timestamp对象
     *
     * @param dateTimeStr 给定的日期字符串
     * @return 返回解析成功后的Timestamp对象
     */
    fun parseTimestamp(dateTimeStr: String): Timestamp? {
        val date = parseDateTime(dateTimeStr)

        return convert(date)
    }

    /**
     * @return 返回当前时间的Timestamp对象
     */
    fun getCurrentTimestamp(): Timestamp {
        return Timestamp(System.currentTimeMillis())
    }

    /**
     * @param date 指定的Date对象
     * @return 将指定的Date对象转换成Timestamp对象
     */
    fun convert(date: Date?): Timestamp? {
        return if (date == null) {
            null
        } else Timestamp(date.time)
    }

    /**
     * @param timestamp 指定的Timestamp对象
     * @return 将指定的Timestamp对象转换成Date对象
     */
    fun convert(timestamp: Timestamp?): Date? {
        return if (timestamp == null) {
            null
        } else Date(timestamp.time)
    }

    /**
     * 对给定的两个日期进行比较，如果date1 比 date2 大，则返回1；如果相等，则返回0；否则返回-1
     *
     * @param date1
     * @param date2
     * @return 对给定的两个日期进行比较，如果date1 比 date2 大，则返回1；如果相等，则返回0；否则返回-1
     */
    fun compare(date1: Date?, date2: Date?): Int {
        if (date1 == null) {
            return -1
        }
        if (date2 == null) {
            return 1
        }
        val timeDiff = date1.time - date2.time

        return if (timeDiff == 0L) 0 else (timeDiff / Math.abs(timeDiff)).toInt()
    }


    // （版本2）得出的结果是1天，我们一般用的方法都会推荐版本2

    fun daysOfTwo(fDate: Date, oDate: Date): Int {
        val aCalendar = Calendar.getInstance()
        aCalendar.time = fDate
        val day1 = aCalendar.get(Calendar.DAY_OF_YEAR)
        aCalendar.time = oDate
        val day2 = aCalendar.get(Calendar.DAY_OF_YEAR)
        return day2 - day1

    }

    /**
     * 获取当前系统之前N天的时间 times几天前
     *
     * @return 返回字符串型的时间 "yyyy-MM-dd HH:mm:ss"
     */
    fun getYesterdayTime(times: Int): String {
        val c = Calendar.getInstance()// 把当前时间中的data自减1
        c.add(Calendar.DAY_OF_MONTH, -times)
        val formatter = SimpleDateFormat(FORMAT_DATETIME)
        return formatter.format(c.time)
    }

    /**
     * 返回两个时间差 例：1小时前
     * tips：如需国际化 需要改造
     */
    fun getDateInterval(startDate: Date, endDate: Date): String {
        if (endDate <= startDate)
            return "刚刚"

        val startCalendar = Calendar.getInstance()
        startCalendar.time = startDate
        val endCalendar = Calendar.getInstance()
        endCalendar.time = endDate

        val year1 = startCalendar.get(Calendar.YEAR)
        val year2 = endCalendar.get(Calendar.YEAR)

        if (year2 > year1) {
            return "${year2 - year1}年前"
        }

        val month1 = startCalendar.get(Calendar.MONTH)
        val month2 = endCalendar.get(Calendar.MONTH)

        if (month2 > month1) {
            return "${month2 - month1}月前"
        }

        val day1 = startCalendar.get(Calendar.DAY_OF_MONTH)
        val day2 = endCalendar.get(Calendar.DAY_OF_MONTH)

        if (day2 > day1) {
            return "${day2 - day1}天前"
        }

        val hour1 = startCalendar.get(Calendar.HOUR_OF_DAY)
        val hour2 = endCalendar.get(Calendar.HOUR_OF_DAY)

        if (hour2 > hour1) {
            return "${hour2 - hour1}小时前"
        }

        val minute1 = startCalendar.get(Calendar.MINUTE)
        val minute2 = endCalendar.get(Calendar.MINUTE)
        if (minute2 > minute1) {
            return "${minute2 - minute1}分钟前"
        }

        val second1 = startCalendar.get(Calendar.SECOND)
        val second2 = endCalendar.get(Calendar.SECOND)

        if (second2 > second1) {
            return "${second2 - second1}秒前"
        }
        return "刚刚"

    }

}